Add gtk_snapshot_push_cross_fade()
authorBenjamin Otte <otte@redhat.com>
Thu, 12 Jan 2017 21:00:38 +0000 (22:00 +0100)
committerBenjamin Otte <otte@redhat.com>
Fri, 13 Jan 2017 02:38:36 +0000 (03:38 +0100)
... and use it.

The function is a bit awkward because it requires 2 calls to
gtk_snapshot_pop(), but once you accept that, it's very convenient to
use, as can be seen by the 2 implementations.

docs/reference/gtk/gtk4-sections.txt
gtk/gtkcssimagecrossfade.c
gtk/gtksnapshot.c
gtk/gtksnapshot.h
gtk/gtksnapshotprivate.h
gtk/gtkstack.c

index b34f82d1aadd41b2480713c6ddd4bfba2b685624..13a4b0d30bfcd6c0eb955efd344329318018cef1 100644 (file)
@@ -4458,6 +4458,7 @@ gtk_snapshot_push_color_matrix
 gtk_snapshot_push_repeat
 gtk_snapshot_push_clip
 gtk_snapshot_push_rounded_clip
+gtk_snapshot_push_cross_fade
 gtk_snapshot_pop
 gtk_snapshot_pop_and_append
 gtk_snapshot_set_transform
index 2b9aab127109134a97a313b6c7fbb968c95594d4..7f80248c2bc7469654bc22c1c7be3976e2278104 100644 (file)
@@ -106,64 +106,15 @@ gtk_css_image_cross_fade_snapshot (GtkCssImage *image,
 {
   GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
 
-  if (cross_fade->progress <= 0.0)
-    {
-      if (cross_fade->start)
-        gtk_css_image_snapshot (cross_fade->start, snapshot, width, height);
-    }
-  else if (cross_fade->progress >= 1.0)
-    {
-      if (cross_fade->end)
-        gtk_css_image_snapshot (cross_fade->end, snapshot, width, height);
-    }
-  else
-    {
-      GskRenderNode *start_node, *end_node;
-      if (cross_fade->start)
-        {
-          gtk_snapshot_push (snapshot, TRUE, "CrossFadeStart");
-          gtk_css_image_snapshot (cross_fade->start, snapshot, width, height);
-          start_node = gtk_snapshot_pop (snapshot);
-        }
-      else
-        start_node = NULL;
-
-      if (cross_fade->end)
-        {
-          gtk_snapshot_push (snapshot, TRUE, "CrossFadeStart");
-          gtk_css_image_snapshot (cross_fade->end, snapshot, width, height);
-          end_node = gtk_snapshot_pop (snapshot);
-        }
-      else
-        end_node = NULL;
+  gtk_snapshot_push_cross_fade (snapshot, cross_fade->progress, "CrossFadeImage<%g>", cross_fade->progress);
 
-      if (start_node && end_node)
-        {
-          GskRenderNode *node = gsk_cross_fade_node_new (start_node, end_node, cross_fade->progress);
-
-          if (snapshot->record_names)
-            gsk_render_node_set_name (node, "CrossFade");
-          gtk_snapshot_append_node (snapshot, node);
+  if (cross_fade->start)
+    gtk_css_image_snapshot (cross_fade->start, snapshot, width, height);
+  gtk_snapshot_pop_and_append (snapshot);
 
-          gsk_render_node_unref (node);
-          gsk_render_node_unref (start_node);
-          gsk_render_node_unref (end_node);
-        }
-      else if (start_node)
-        {
-          gtk_snapshot_push_opacity (snapshot, 1.0 - cross_fade->progress, "CrossFadeStart");
-          gtk_snapshot_append_node (snapshot, start_node);
-          gtk_snapshot_pop_and_append (snapshot);
-          gsk_render_node_unref (start_node);
-        }
-      else if (end_node)
-        {
-          gtk_snapshot_push_opacity (snapshot, cross_fade->progress, "CrossFadeEnd");
-          gtk_snapshot_append_node (snapshot, end_node);
-          gtk_snapshot_pop_and_append (snapshot);
-          gsk_render_node_unref (end_node);
-        }
-    }
+  if (cross_fade->end)
+    gtk_css_image_snapshot (cross_fade->end, snapshot, width, height);
+  gtk_snapshot_pop_and_append (snapshot);
 }
 
 static gboolean
index 08db8c5b634da124cda0b173fb42ac66aa828f8b..d79f9039c13e41428f5283518a4a82c8bfee84de 100644 (file)
@@ -647,7 +647,6 @@ gtk_snapshot_push_shadow (GtkSnapshot            *snapshot,
   GtkSnapshotState *state;
   char *str;
 
-
   if (name && snapshot->record_names)
     {
       va_list args;
@@ -676,6 +675,127 @@ gtk_snapshot_push_shadow (GtkSnapshot            *snapshot,
   snapshot->state = state;
 }
 
+static GskRenderNode *
+gtk_snapshot_collect_cross_fade_end (GtkSnapshotState *state,
+                                     GskRenderNode   **nodes,
+                                     guint             n_nodes,
+                                     const char       *name)
+{
+  GskRenderNode *start_node, *end_node, *node;
+
+  end_node = gtk_snapshot_collect_default (state, nodes, n_nodes, name);
+  start_node = state->data.cross_fade.start_node;
+
+  if (state->data.cross_fade.progress <= 0.0)
+    {
+      node = start_node;
+
+      if (end_node)
+        gsk_render_node_unref (end_node);
+    }
+  else if (state->data.cross_fade.progress >= 1.0)
+    {
+      node = end_node;
+
+      if (start_node)
+        gsk_render_node_unref (start_node);
+    }
+  else if (start_node && end_node)
+    {
+      node = gsk_cross_fade_node_new (start_node, end_node, state->data.cross_fade.progress);
+      gsk_render_node_set_name (node, name);
+
+      gsk_render_node_unref (start_node);
+      gsk_render_node_unref (end_node);
+    }
+  else if (start_node)
+    {
+      node = gsk_opacity_node_new (start_node, 1.0 - state->data.cross_fade.progress);
+      gsk_render_node_set_name (node, name);
+
+      gsk_render_node_unref (start_node);
+    }
+  else if (end_node)
+    {
+      node = gsk_opacity_node_new (end_node, state->data.cross_fade.progress);
+      gsk_render_node_set_name (node, name);
+
+      gsk_render_node_unref (end_node);
+    }
+  else
+    {
+      node = NULL;
+    }
+
+  return node;
+}
+
+static GskRenderNode *
+gtk_snapshot_collect_cross_fade_start (GtkSnapshotState *state,
+                                       GskRenderNode   **nodes,
+                                       guint             n_nodes,
+                                       const char       *name)
+{
+  state->parent->data.cross_fade.start_node = gtk_snapshot_collect_default (state, nodes, n_nodes, name);
+  
+  return NULL;
+}
+
+/**
+ * gtk_snapshot_push_cross_fade:
+ * @snapshot: a #GtkSnapshot
+ * @progress: progress between 0.0 and 1.0
+ * @name: printf format string for name of the pushed node
+ * @...: printf-style arguments for the @name string
+ *
+ * Snapshots a cross-fade operation between two images with the
+ * given @progress.
+ *
+ * Until the first call to gtk_snapshot_pop(), the start image
+ * will be snapshot. After that call, the end image will be recorded
+ * until the second call to gtk_snapshot_pop().
+ *
+ * Calling this function requires 2 calls to gtk_snapshot_pop().
+ **/
+void
+gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
+                              double       progress,
+                              const char  *name,
+                              ...)
+{
+  GtkSnapshotState *state;
+  char *str;
+
+  if (name && snapshot->record_names)
+    {
+      va_list args;
+
+      va_start (args, name);
+      str = g_strdup_vprintf (name, args);
+      va_end (args);
+    }
+  else
+    str = NULL;
+
+  state = gtk_snapshot_state_new (snapshot->state,
+                                  str,
+                                  snapshot->state->clip_region,
+                                  snapshot->state->translate_x,
+                                  snapshot->state->translate_y,
+                                  gtk_snapshot_collect_cross_fade_end);
+  state->data.cross_fade.progress = progress;
+  state->data.cross_fade.start_node = NULL;
+
+  state = gtk_snapshot_state_new (state,
+                                  str,
+                                  state->clip_region,
+                                  state->translate_x,
+                                  state->translate_y,
+                                  gtk_snapshot_collect_cross_fade_start);
+
+  snapshot->state = state;
+}
+
 /**
  * gtk_snapshot_pop:
  * @snapshot: a #GtkSnapshot
index 0b691c3486ab2d473bdfc1833157574b1d288a88..7ac7a43481259defbc7c3ce501c429c9f497fb97 100644 (file)
@@ -80,6 +80,11 @@ void            gtk_snapshot_push_shadow                (GtkSnapshot
                                                          const char             *name,
                                                          ...) G_GNUC_PRINTF (4, 5);
 GDK_AVAILABLE_IN_3_90
+void            gtk_snapshot_push_cross_fade            (GtkSnapshot            *snapshot,
+                                                         double                  progress,
+                                                         const char             *name,
+                                                         ...) G_GNUC_PRINTF (3, 4);
+GDK_AVAILABLE_IN_3_90
 GskRenderNode * gtk_snapshot_pop                        (GtkSnapshot            *snapshot) G_GNUC_WARN_UNUSED_RESULT;
 GDK_AVAILABLE_IN_3_90
 void            gtk_snapshot_pop_and_append             (GtkSnapshot            *snapshot);
index 91d1b66ef6a9ac53e556fc85a7c2151e4d7fb44d..3989bc5fde7dee1a56fc7440fdd2f24e0a939999 100644 (file)
@@ -67,6 +67,10 @@ struct _GtkSnapshotState {
       GskShadow *shadows;
       GskShadow a_shadow; /* Used if n_shadows == 1 */
     } shadow;
+    struct {
+      double progress;
+      GskRenderNode *start_node;
+    } cross_fade;
   } data;
 };
 
index d1f4767ed8b82ee4414f7436cd7633fb9ea942ca..b1448f28b703f79323208aa07ae19987688c9143 100644 (file)
@@ -1914,44 +1914,25 @@ gtk_stack_snapshot_crossfade (GtkWidget   *widget,
   GtkStack *stack = GTK_STACK (widget);
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
   gdouble progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
-  GskRenderNode *end_node, *node;
-  char *name;
 
-  gtk_snapshot_push (snapshot, TRUE, "GtkStackCrossFadeEnd");
-  gtk_widget_snapshot_child (widget,
-                             priv->visible_child->widget,
-                             snapshot);
-  end_node = gtk_snapshot_pop (snapshot);
+  gtk_snapshot_push_cross_fade (snapshot, progress, "CrossFade<%g>", progress);
 
   if (priv->last_visible_node)
     {
       graphene_matrix_t identity;
-      GskRenderNode *start_node;
 
       graphene_matrix_init_identity (&identity);
 
       gtk_snapshot_push_transform (snapshot, &identity, "CrossFadeStart");
       gtk_snapshot_append_node (snapshot, priv->last_visible_node);
-      start_node = gtk_snapshot_pop (snapshot);
-      node = gsk_cross_fade_node_new (start_node, end_node, progress);
-      gsk_render_node_unref (start_node);
-    }
-  else
-    {
-      node = gsk_opacity_node_new (end_node, 1.0 - progress);
-    }
-
-  if (snapshot->record_names)
-    {
-      name = g_strdup_printf ("CrossFade<%g>", progress);
-      gsk_render_node_set_name (node, name);
-      g_free (name);
+      gtk_snapshot_pop_and_append (snapshot);
     }
+  gtk_snapshot_pop_and_append (snapshot);
 
-  gtk_snapshot_append_node (snapshot, node);
-
-  gsk_render_node_unref (node);
-  gsk_render_node_unref (end_node);
+  gtk_widget_snapshot_child (widget,
+                             priv->visible_child->widget,
+                             snapshot);
+  gtk_snapshot_pop_and_append (snapshot);
 }
 
 static void